#ifndef FILEEXPLORER_H
#define FILEEXPLORER_H

#include <wx/wx.h>
#include <wx/treectrl.h>
#include <wx/combobox.h>
#include <wx/dynarray.h>

#include <vector>
#include "FileExplorerSettings.h"
#include "FileExplorerUpdater.h"
#include "directorymonitor.h"

class UpdateQueue;

class Expansion;

typedef std::vector<Expansion*> ExpList;

class VCSstate {
  public:
    int state;
    wxString path;
};

WX_DECLARE_OBJARRAY( VCSstate, VCSstatearray );

class Expansion {
  public:
    Expansion() { name = _T( "" );}
    ~Expansion() {for( size_t i = 0; i < children.size(); i++ ) delete children[i];}
    wxString name;
    ExpList children;
};

class wxFEDropTarget;


class FileTreeCtrl: public wxTreeCtrl {
  public:
    FileTreeCtrl( wxWindow* parent, wxWindowID id, const wxPoint& pos = wxDefaultPosition,
                  const wxSize& size = wxDefaultSize, long style = wxTR_HAS_BUTTONS | wxTR_MULTIPLE | wxTR_NO_LINES,
                  const wxValidator& validator = wxDefaultValidator,
                  const wxString& name = _T( "treeCtrl" ) );
    FileTreeCtrl();
    FileTreeCtrl( wxWindow *parent );
    void OnKeyDown( wxKeyEvent &e );

    virtual ~FileTreeCtrl();

  protected:
    virtual int OnCompareItems( const wxTreeItemId& item1, const wxTreeItemId& item2 );
    DECLARE_DYNAMIC_CLASS( FileTreeCtrl )
    DECLARE_EVENT_TABLE()
};

class FileExplorer: public wxPanel {
    friend class FileExplorerUpdater;
    friend class VCSFileLoader;
    friend class wxFEDropTarget;
  public:
    FileExplorer( wxWindow *parent, wxWindowID id = wxID_ANY,
                  const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
                  long style = wxTAB_TRAVERSAL | wxTE_PROCESS_ENTER, const wxString& name = _T( "文件管理器" ) );
    ~FileExplorer();
    bool SetRootFolder( wxString root );
    wxString GetRootFolder() {return m_root;}
    void FindFile( const wxString & ) {}
    void MoveFiles( const wxString &destination, const wxArrayString &selectedfiles );
    void CopyFiles( const wxString &destination, const wxArrayString &selectedfiles );

  private:

    bool IsBrowsingVCSTree();
    bool IsBrowsingWorkingCopy();
    void OnRightClick( wxTreeEvent &event );
    void OnActivate( wxTreeEvent &event );
    void OnExpand( wxTreeEvent &event );
    void OnEnterLoc( wxCommandEvent &event );
    void OnEnterWild( wxCommandEvent &event );
    void OnVCSControl( wxCommandEvent &event );
    void OnVCSChangesCheck( wxCommandEvent &event );
    void OnChooseLoc( wxCommandEvent &event );
    void OnChooseWild( wxCommandEvent &event );
    void OnSetLoc( wxCommandEvent &event );
    void OnNewFile( wxCommandEvent &event );
    void OnOpenInEditor( wxCommandEvent &event );
    void DoOpenInEditor( const wxString &filename );
    void OnVCSFileLoaderComplete( wxCommandEvent &event );
    void OnNewFolder( wxCommandEvent &event );
    void OnAddFavorite( wxCommandEvent &event );
    void OnCopy( wxCommandEvent &event );
    void OnDuplicate( wxCommandEvent &event );
    void OnMove( wxCommandEvent &event );
    void OnDelete( wxCommandEvent &event );
    void OnRename( wxCommandEvent &event );
    void OnExpandAll( wxCommandEvent &event );
    void OnCollapseAll( wxCommandEvent &event );
    void OnSettings( wxCommandEvent &event );
    void OnShowHidden( wxCommandEvent &event );
    void OnParseCVS( wxCommandEvent &event );
    void OnParseSVN( wxCommandEvent &event );
    void OnParseHG( wxCommandEvent &event );
    void OnParseBZR( wxCommandEvent &event );
    void OnParseGIT( wxCommandEvent &event );
    void OnUpButton( wxCommandEvent &event );
    void OnRefresh( wxCommandEvent &event );
    void OnVCSDiff( wxCommandEvent &event );
    void OnBeginDragTreeItem( wxTreeEvent &event );
    void OnEndDragTreeItem( wxTreeEvent &event );
    void OnKeyDown( wxKeyEvent &event );

    void OnAddToProject( wxCommandEvent &event );


    void OnDirMonitor( wxDirectoryMonitorEvent &e );
    void OnUpdateTreeItems( wxCommandEvent &event );
    void OnTimerCheckUpdates( wxTimerEvent &event );

    void UpdateAbort();
    void ResetDirMonitor();

    void WriteConfig();
    void ReadConfig();

    wxArrayString GetSelectedPaths();
    bool IsFilesOnly( wxArrayTreeItemIds tis );
    void FindFile( const wxString &findfilename, const wxTreeItemId &ti );
    void FocusFile( const wxTreeItemId &ti );
    bool IsInSelection( const wxTreeItemId &ti );
    wxString GetFullPath( const wxTreeItemId &ti );
    bool GetItemFromPath( const wxString &path, wxTreeItemId &ti );
    void GetExpandedNodes( wxTreeItemId ti, Expansion *exp );
    void GetExpandedPaths( wxTreeItemId ti, wxArrayString &paths );
    wxTreeItemId GetNextExpandedNode( wxTreeItemId ti );
    bool ValidateRoot();
    void Refresh( wxTreeItemId ti );
    void RefreshExpanded( wxTreeItemId ti );
    void SetImages();
    wxString m_root;
    wxString m_commit;
    FileTreeCtrl *m_Tree;
    wxComboBox *m_Loc;
    wxComboBox *m_WildCards;
    wxButton *m_UpButton;
    wxBoxSizer *m_Box_VCS_Control;
    wxChoice *m_VCS_Control;
    wxStaticText *m_VCS_Type;
    wxCheckBox *m_VCS_ChangesOnly;
    bool m_show_hidden;
    wxArrayTreeItemIds m_selectti;
    FavoriteDirs m_favdirs;


    wxTimer *m_updatetimer;
    FileExplorerUpdater *m_updater;
    bool m_updater_cancel;
    bool m_update_expand;
    wxTreeItemId m_updating_node;
    wxTreeItemId m_updated_node;
    bool m_update_active;
    UpdateQueue *m_update_queue;
    wxDirectoryMonitor *m_dir_monitor;
    wxFEDropTarget *m_droptarget;

    int m_ticount;
    wxString m_dragtest;
    size_t m_findmatchcount;
    wxArrayString m_findmatch;

    LoaderQueue m_vcs_file_loader_queue;
    VCSFileLoader *m_vcs_file_loader;

    bool m_parse_cvs;
    bool m_parse_svn;
    bool m_parse_hg;
    bool m_parse_bzr;
    bool m_parse_git;
    bool m_kill;
    DECLARE_EVENT_TABLE()
};



#endif
